package org.meetunexpectedly.service.video.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.meetunexpectedly.entity.response.AuditResponse;
import org.meetunexpectedly.entity.user.User;
import org.meetunexpectedly.entity.video.Comment;
import org.meetunexpectedly.entity.video.CommentThumb;
import org.meetunexpectedly.entity.video.Video;
import org.meetunexpectedly.entity.vo.BasePage;
import org.meetunexpectedly.exception.BaseException;
import org.meetunexpectedly.holder.UserHolder;
import org.meetunexpectedly.mapper.video.CommentMapper;
import org.meetunexpectedly.service.audit.TextAuditService;
import org.meetunexpectedly.service.user.UserService;
import org.meetunexpectedly.service.video.CommentService;
import org.meetunexpectedly.service.video.CommentThumbService;
import org.meetunexpectedly.service.video.VideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;

/**
 * @Description: 评论服务实现类
 * @Author: pupil
 * @Date: 2025/1/19 下午 9:48
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {
    @Autowired
    private VideoService videoService;

    @Autowired
    private TextAuditService textAuditService;

    @Autowired
    private UserService userService;

    @Autowired
    private CommentThumbService commentThumbService;

    @Override
    public Boolean addComment(Long videoId, Long parentId, String content, Long userId) {
        if (content == null || videoId == null || parentId < 0) {
            throw new BaseException("评论内容、视频id不能为空");
        }
        // 判断视频是否存在
        Video video = videoService.getById(videoId);
        if (video == null) {
            throw new BaseException("指定视频不存在");
        }
        // 进行内容文本审核
        AuditResponse audit = textAuditService.audit(content);
        if (audit.getFlag()) {
            throw new BaseException("评论内容违规");
        }

        Comment comment = new Comment();
        // 设置评论内容
        comment.setContent(content);
        // 设置评论或者回复用户id
        comment.setFromUserId(userId);
        // 设置视频id
        comment.setVideoId(videoId);
        // 设置视频作者id
        comment.setVideoUserId(video.getUserId());
        // 结果
        boolean result = false;
        // 一级评论
        if (parentId == null) {
            // 设置父级id，一级评论的父级id为0
            comment.setParentId(0L);
            result = this.saveOrUpdate(comment);
            // 设置顶级id，一级评论的顶级id为自己的id
            comment.setRootId(comment.getId());
        } else {
            // 设置父级评论id
            comment.setParentId(parentId);
            // 查询父级评论
            Comment parentComment = this.getById(parentId);
            // 设置被回复用户id
            comment.setToUserId(parentComment.getFromUserId());
            // 寻找顶级id
            while (parentComment.getParentId() != 0L) {
                parentComment = this.getById(parentId);
            }
            // 更新顶级评论的子评论数
            updateChildCount(parentComment, 1L);
            // 设置顶级id
            comment.setRootId(parentComment.getId());
        }

        result = this.saveOrUpdate(comment);

        if (result) {
            // 评论数+1
            updateVideoCommentCount(video, 1L);
        }
        return result;
    }

    @Override
    public Collection<Comment> getCommentByVideoId(BasePage basePage, Long videoId) {
        // 判断分页信息是否为空
        if (ObjectUtils.isEmpty(basePage)) {
            throw new BaseException("分页信息不能为空");
        }

        // 判断视频是否存在
        Video video = videoService.getById(videoId);
        if (video == null) {
            throw new BaseException("指定视频不存在");
        }

        LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
        // 分页查询
        IPage<Comment> page = this.page(basePage.page(),
                wrapper.eq(Comment::getVideoId, videoId)
                        .eq(Comment::getParentId, 0L)
                        .orderByDesc(Comment::getGmtUpdated));
        Long userId = UserHolder.get();
        Collection<Comment> commentList = setUser(page, userId);
        return commentList;
    }

    @Override
    public Collection<Comment> getCommentByRootId(BasePage basePage, Long rootId) {
        // 判断分页信息是否为空
        if (ObjectUtils.isEmpty(basePage)) {
            throw new BaseException("分页信息不能为空");
        }

        Comment rootComment = this.getById(rootId);
        if (ObjectUtils.isEmpty(rootComment)) {
            throw new BaseException("指定评论不存在");
        }

        // 分页查询
        IPage<Comment> page = this.page(basePage.page(), new LambdaQueryWrapper<Comment>()
                .eq(Comment::getRootId, rootId)
                .ne(Comment::getParentId, 0L)
                .orderByDesc(Comment::getGmtUpdated));

        Long userId = UserHolder.get();
        Collection<Comment> commentList = setUser(page, userId);
        return commentList;
    }

    @Override
    public Boolean deleteCommentById(Long commentId, Long userId) {
        if (userId == null) {
            throw new BaseException("userId不能为空");
        }

        Comment comment = this.getById(commentId);
        if (ObjectUtils.isEmpty(comment)) {
            throw new BaseException("指定评论不存在");
        }

        // 查出删除的相关评论数
        int count = this.count(new LambdaQueryWrapper<Comment>()
                .eq(Comment::getId, comment.getId())
                .or()
                .eq(Comment::getRootId, comment.getId()));

        // 删除根评论和子评论
        boolean result = this.remove(new LambdaQueryWrapper<Comment>()
                .eq(Comment::getId, comment.getId())
                .or()
                .eq(Comment::getRootId, comment.getId()));

        if (result) {
            // 减少视频对应的评论数
            Long videoId = comment.getVideoId();
            Video video = videoService.getById(videoId);
            updateVideoCommentCount(video, Long.valueOf(-count));
        }
        return result;
    }

    @Override
    public Boolean thumbUpComment(Long commentId) {
        Comment comment = this.getById(commentId);
        if (comment == null) {
            throw new BaseException("指定评论不存在");
        }

        CommentThumb commentThumb = new CommentThumb();
        Long userId = UserHolder.get();
        commentThumb.setUserId(userId);
        commentThumb.setCommentId(commentId);

        Boolean result = commentThumbService.thumbUp(commentThumb);
        updateThumbUp(comment, result ? 1L : -1L);

        return result;
    }


    /**
     * 查看点赞状态
     *
     * @param comment
     * @param userId
     * @return
     */
    private boolean checkState(Comment comment, Long userId) {
        Long commentId = comment.getId();
        return commentThumbService.thumbUpState(commentId, userId);
    }

    /**
     * 设置user
     *
     * @param page   分页查询结果
     * @param userId 用户id
     * @return
     */
    private Collection<Comment> setUser(IPage<Comment> page, Long userId) {
        Collection<Comment> commentList = page.getRecords();
        if (ObjectUtils.isEmpty(commentList)) {
            return Collections.EMPTY_LIST;
        }

        commentList.stream().filter(comment -> comment != null).collect(Collectors.toList());

        for (Comment comment : commentList) {
            User fromUser = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getId, comment.getFromUserId()).select(User::getId, User::getNickName,User::getAvatar));
            comment.setFromUser(fromUser);
            User toUser = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getId, comment.getToUserId()).select(User::getId, User::getNickName,User::getAvatar));
            comment.setToUser(toUser);
            // 设置点赞数
            Long count = Long.valueOf(commentThumbService.count(new LambdaQueryWrapper<CommentThumb>().eq(CommentThumb::getCommentId, comment.getId())));
            comment.setThumbCount(count);
            // 设置点赞状态
            comment.setThumb(checkState(comment, userId));
        }
        return commentList;
    }

    /**
     * 更新子评论数
     *
     * @param comment 评论
     * @param value   子评论数
     */
    private void updateChildCount(Comment comment, Long value) {
        UpdateWrapper<Comment> updateWrapper = new UpdateWrapper<>();
        updateWrapper.setSql("child_count = child_count + " + value);
        updateWrapper.lambda().eq(Comment::getId, comment.getId()).eq(Comment::getChildCount, comment.getChildCount());
        this.update(comment, updateWrapper);
    }


    /**
     * 更新评论点赞数
     *
     * @param comment 评论
     * @param value   点赞数
     */
    private void updateThumbUp(Comment comment, Long value) {
        UpdateWrapper<Comment> updateWrapper = new UpdateWrapper<>();
        updateWrapper.setSql("thumb_count = thumb_count + " + value);
        updateWrapper.lambda().eq(Comment::getId, comment.getId()).eq(Comment::getThumbCount, comment.getThumbCount());
        this.update(comment, updateWrapper);
    }

    /**
     * 更新视频评论数
     *
     * @param video 视频
     * @param value 评论数
     */
    private void updateVideoCommentCount(Video video, Long value) {
        UpdateWrapper<Video> updateWrapper = new UpdateWrapper<>();
        updateWrapper.setSql("comment_count = comment_count +" + value);
        updateWrapper.lambda().eq(Video::getId, video.getId()).eq(Video::getCommentCount, video.getCommentCount());
        videoService.update(video, updateWrapper);
    }
}
